home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / proc / procExec.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  60KB  |  2,025 lines

  1. /* procExec.c --
  2.  *
  3.  *    Routines to exec a program.  There is no monitor required in this
  4.  *    file.  Access to the proc table is synchronized by locking the PCB
  5.  *    when modifying the genFlags field.
  6.  *
  7.  * Copyright (C) 1985, 1988 Regents of the University of California
  8.  * Permission to use, copy, modify, and distribute this
  9.  * software and its documentation for any purpose and without
  10.  * fee is hereby granted, provided that the above copyright
  11.  * notice appear in all copies.  The University of California
  12.  * makes no representations about the suitability of this
  13.  * software for any purpose.  It is provided "as is" without
  14.  * express or implied warranty.
  15.  */
  16.  
  17. #ifndef lint
  18. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/proc/procExec.c,v 9.35 92/07/19 22:14:08 shirriff Exp $ SPRITE (Berkeley)";
  19. #endif /* not lint */
  20.  
  21. #include <sprite.h>
  22. #include <procMach.h>
  23. #include <mach.h>
  24. #include <proc.h>
  25. #include <procInt.h>
  26. #include <sync.h>
  27. #include <sched.h>
  28. #include <fs.h>
  29. #include <fsio.h>
  30. #include <stdlib.h>
  31. #include <sig.h>
  32. #include <spriteTime.h>
  33. #include <list.h>
  34. #include <vm.h>
  35. #include <sys.h>
  36. #include <procMigrate.h>
  37. #include <procUnixStubs.h>
  38. #include <status.h>
  39. #include <string.h>
  40. #include <byte.h>
  41. #include <rpc.h>
  42. #include <prof.h>
  43. #include <fsutil.h>
  44. #include <ctype.h>
  45. #include <stdio.h>
  46. #include <bstring.h>
  47. #include <vmMach.h>
  48. #include <file.h>
  49. /*
  50.  * This will go away when libc is changed.
  51.  */
  52. #ifndef PROC_MAX_ENVIRON_LENGTH
  53. #define PROC_MAX_ENVIRON_LENGTH (PROC_MAX_ENVIRON_NAME_LENGTH + \
  54.                  PROC_MAX_ENVIRON_VALUE_LENGTH)
  55. #endif /*  PROC_MAX_ENVIRON_LENGTH */
  56.  
  57. /* 
  58.  * Maximum number of argument to an interpreter: script name, interpreter 
  59.  * flags, script name (again), and nil pointer to end the array.
  60.  */
  61. #define MAX_INTERP_ARGS        4
  62.  
  63. #define UNIX_CODE 1
  64.  
  65. typedef struct {
  66.     List_Links    links;
  67.     Address    stringPtr;
  68.     int        stringLen;
  69. } ArgListElement;
  70.  
  71. extern int debugProcStubs;
  72.  
  73. /*
  74.  * Define the information needed to perform an exec: the user's stack,
  75.  * where to put it, and whether to debug on startup.  We define a structure
  76.  * containing the "meta-info" that isn't actually copied onto the user's
  77.  * stack, and then another structure that also includes argc.  (By
  78.  * separating the header into a separate structure, it's easier to take its
  79.  * size.)
  80.  * 
  81.  * Note that the actual values for argv and envp passed to main() are
  82.  * calculated by _start() based on the address of argc and are not actually
  83.  * put on the stack given to the exec'ed process.  The size of the structure
  84.  * to be copied onto the user's stack is the size in the 'size' field
  85.  * minus the size of the header.
  86.  *
  87.  * The fileName and argString fields are used only when doing a remote exec.
  88.  */
  89. typedef struct {
  90.     Address base;        /* base of the structure in user space */
  91.     int size;            /* size of the entire structure */
  92.     char *fileName;        /* pointer to buffer containing name of file
  93.                  * to exec */
  94.     int fileNameLength;        /* length of file name buffer */
  95.     char *argString;        /* pointer to buffer containing full list of
  96.                  * arguments, for ps listing */
  97.     int argLength;        /* length of argString buffer */
  98. } ExecEncapHeader;
  99.  
  100. typedef struct {
  101.     ExecEncapHeader hdr;    /* meta-information; see above */
  102.     /*
  103.      * User stack data starts here.
  104.      */
  105.     int argc;            /* Number of arguments */
  106.     /*
  107.      * argv[] goes here
  108.      * envp[] goes here
  109.      * *argv[] goes here
  110.      * *envp[] goes here
  111.      */
  112. } ExecEncapState;
  113.  
  114. /*
  115.  * Define a structure to hold all the information about arguments
  116.  * and environment variables (pointer and length).  This makes it easier
  117.  * to pass a NIL pointer for the whole thing, and to keep them in one
  118.  * place.  The number of arguments/environment pointers includes the 
  119.  * null pointer at the end of the array.
  120.  */
  121.  
  122. typedef struct {
  123.     Boolean    userMode;    /* TRUE if the arguments are in user space */
  124.     char    **argPtrArray;    /* The array of argument pointers. */
  125.     int        numArgs;    /* The number of arguments in the argArray. */
  126.     int        argLength;    /* actual size of argArray */
  127.     char    **envPtrArray;    /* The array of environment pointers. */
  128.     int        numEnvs;    /* The number of arguments in the envArray. */
  129.     int        envLength;    /* actual size of envArray */
  130. } UserArgs;
  131.  
  132. /*
  133.  * Forward declarations.
  134.  */
  135. static ReturnStatus     DoExec _ARGS_((char fileName[], 
  136.                 UserArgs *userArgsPtr, 
  137.                 ExecEncapState **encapPtrPtr, Boolean debugMe));
  138. static ReturnStatus     SetupInterpret _ARGS_((char *buffer, 
  139.                 int sizeRead, Fs_Stream **filePtrPtr, 
  140.                 char **interpNamePtr, char **interpFlagsPtr, 
  141.                 ProcObjInfo *objInfoPtr));
  142. static ReturnStatus     SetupArgs _ARGS_((UserArgs *userArgsPtr, 
  143.                 char **extraArgArray, Address *argStackPtr, 
  144.                 char **argStringPtr));
  145. static ReturnStatus     GrabArgArray _ARGS_((int maxLength, Boolean userProc, 
  146.                 char **extraArgArray, char **argPtrArray, 
  147.                 int *numArgsPtr, List_Links *argList, 
  148.                 int *realLengthPtr, int *paddedLengthPtr));
  149. static Boolean         SetupVM _ARGS_((register Proc_ControlBlock *procPtr, 
  150.                 register ProcObjInfo *objInfoPtr, 
  151.                 Fs_Stream *codeFilePtr, Boolean usedFile, 
  152.                 Vm_Segment **codeSegPtrPtr, 
  153.                 register Vm_ExecInfo *execInfoPtr));
  154. static Boolean        ZeroHeapEnd _ARGS_ ((Vm_ExecInfo *execInfoPtr));
  155.  
  156. #ifdef notdef
  157. /*
  158.  * Define a type to include the information that is passed from
  159.  * the local setup routine to the routine that performs the actual
  160.  * exec.
  161.  */
  162. typedef struct {
  163.     Proc_AOUT                *aoutPtr;
  164.     Vm_ExecInfo                *execInfoPtr;
  165.     Proc_AOUT                aout;
  166.     Vm_Segment                *codeSegPtr = (Vm_Segment *) NIL;
  167.     char                *argString = (char *) NIL;
  168.     Address                argBuffer = (Address) NIL;
  169.     Fs_Stream                *filePtr;
  170.     int                    entry;
  171.     Boolean                usedFile;
  172.     int                    uid;
  173.     int                    gid;
  174.     ExecEncapState            *hdrPtr;
  175. }
  176. #endif    
  177.  
  178. /*
  179.  * Define entry points for exec.  They are distinct due to compatibility
  180.  * considerations.  We can deal with them better when we convert the
  181.  * system calls to be more unix-like.
  182.  */
  183.  
  184. /*
  185.  *----------------------------------------------------------------------
  186.  *
  187.  * Proc_RemoteExec --
  188.  *
  189.  *    Process the Exec system call on a remote host.
  190.  *    This does the same setup as Proc_Exec, and then initiates a migration
  191.  *    with the stack of the new process contained in a buffer reachable
  192.  *    from the process control block.
  193.  *
  194.  * Results:
  195.  *    SUCCESS indicates that the process has been signalled to cause it
  196.  *    to migrate before it exits the kernel.  Any other status is
  197.  *    an error that should be returned to the process as usual.
  198.  *
  199.  * Side effects:
  200.  *    Memory is allocated for the buffer containing the exec info.
  201.  *    This should be freed by the migration encapsulation routine.
  202.  *
  203.  *----------------------------------------------------------------------
  204.  */
  205.  
  206. int
  207. Proc_RemoteExec(fileName, argPtrArray, envPtrArray, host)
  208.     char    *fileName;    /* The name of the file to exec. */
  209.     char    **argPtrArray;    /* The array of arguments to the exec'd 
  210.                  * program. */
  211.     char    **envPtrArray;    /* The array of environment variables for
  212.                  * the exec'd program. */
  213.     int        host;        /* ID of host on which to exec. */
  214. {
  215.     int status;
  216.     
  217.     /*
  218.      * XXX need to check permission to migrate.
  219.      */
  220.  
  221.     status = Proc_Exec(fileName, argPtrArray, envPtrArray, FALSE, host);
  222.     /*
  223.      * XXX on failure, need to clean up.
  224.      */
  225.     return(status);
  226. }
  227.  
  228.  
  229. /*
  230.  *----------------------------------------------------------------------
  231.  *
  232.  * Proc_ExecEnv --
  233.  *
  234.  *    Here for backward compatibility.  It does an exec on the
  235.  *    local host.
  236.  *
  237.  * Results:
  238.  *    This process will not return unless an error occurs in which case it
  239.  *    returns the error.
  240.  *
  241.  * Side effects:
  242.  *    None.
  243.  *
  244.  *----------------------------------------------------------------------
  245.  */
  246.  
  247. int
  248. Proc_ExecEnv(fileName, argPtrArray, envPtrArray, debugMe)
  249.     char    *fileName;    /* The name of the file to exec. */
  250.     char    **argPtrArray;    /* The array of arguments to the exec'd 
  251.                  * program. */
  252.     char    **envPtrArray;    /* The array of environment variables
  253.                  * of the form NAME=VALUE. */ 
  254.     Boolean    debugMe;    /* TRUE means that the process is 
  255.                  * to be sent a SIG_DEBUG signal before
  256.                      * executing its first instruction. */
  257. {
  258.     return(Proc_Exec(fileName, argPtrArray, envPtrArray, debugMe, 0));
  259. }
  260.  
  261.  
  262. /*
  263.  *----------------------------------------------------------------------
  264.  *
  265.  * Proc_Exec --
  266.  *
  267.  *    The ultimate entry point for the Exec system call.  This
  268.  *     handles both local and remote exec's.  It calls SetupExec to
  269.  *     initialize the file pointer, a.out info, user's stack image, etc.
  270.  *    The a.out information is used if the exec is
  271.  *     performed on this machine, but for a remote exec, the file
  272.  *    is reopened in case of different machine types.  The stack is
  273.  *     used locally or copied to the remote host.
  274.  *
  275.  * Results:
  276.  *    For local exec's, this procedure will not return unless an error
  277.  *    occurs, in which case it returns the error.  For remote exec's,
  278.  *    SUCCESS is returned, and the calling routine arranges for
  279.  *    the process to hit a migration signal before continuing.
  280.  *
  281.  * Side effects:
  282.  *    The argument & environment arrays are made accessible.  Memory
  283.  *    is allocated for the file name.  
  284.  *    The DoExec routine makes the arrays unaccessible.  It frees the
  285.  *    space for the file name, unless the name is used for a remote
  286.  *    exec, in which case it is left around until after migration.
  287.  *
  288.  *----------------------------------------------------------------------
  289.  */
  290.  
  291. int
  292. Proc_Exec(fileName, argPtrArray, envPtrArray, debugMe, host)
  293.     char    *fileName;    /* The name of the file to exec. */
  294.     char    **argPtrArray;    /* The array of arguments to the exec'd 
  295.                  * program. */
  296.     char    **envPtrArray;    /* The array of environment variables
  297.                  * of the form NAME=VALUE. */ 
  298.     Boolean    debugMe;    /* TRUE means that the process is 
  299.                  * to be sent a SIG_DEBUG signal before
  300.                      * executing its first instruction. */
  301.     int        host;        /* Host to which to do remote exec, or 0
  302.                  * for local host. */
  303. {
  304.     char        **newArgPtrArray;
  305.     int            newArgPtrArrayLength;
  306.     char        **newEnvPtrArray;
  307.     int            newEnvPtrArrayLength;
  308.     UserArgs        userArgs;
  309.     int            strLength;
  310.     int            accessLength;
  311.     ReturnStatus    status;
  312.     char         *execFileName;
  313.     ExecEncapState    *encapPtr;
  314.     ExecEncapState    **encapPtrPtr;
  315.     Proc_ControlBlock     *procPtr;
  316.     
  317.  
  318.  
  319.     /*
  320.      * Make the file name accessible. 
  321.      */
  322.  
  323.     status = Proc_MakeStringAccessible(FS_MAX_PATH_NAME_LENGTH, &fileName,
  324.                        &accessLength, &strLength);
  325.     if (status != SUCCESS) {
  326.     return(status);
  327.     }
  328.  
  329.     execFileName = malloc(accessLength);
  330.     (void) strncpy(execFileName, fileName, accessLength);
  331.     Proc_MakeUnaccessible((Address) fileName, accessLength);
  332.  
  333.     /*
  334.      * Make the arguments array accessible.
  335.      */
  336.  
  337.     if (argPtrArray != (char **) USER_NIL) {
  338.     Vm_MakeAccessible(VM_READONLY_ACCESS,
  339.               (PROC_MAX_EXEC_ARGS + 1) * sizeof(Address),
  340.               (Address) argPtrArray, 
  341.                   &newArgPtrArrayLength, (Address *) &newArgPtrArray);
  342.     if (newArgPtrArrayLength == 0) {
  343.         return(SYS_ARG_NOACCESS);
  344.     }
  345.     } else {
  346.     newArgPtrArray = (char **) NIL;
  347.     newArgPtrArrayLength = 0;
  348.     }
  349.  
  350.     /*
  351.      * Make the environments array accessible.
  352.      */
  353.  
  354.     if (envPtrArray != (char **) USER_NIL) {
  355.     Vm_MakeAccessible(VM_READONLY_ACCESS,
  356.               (PROC_MAX_ENVIRON_SIZE + 1) * sizeof(Address),
  357.               (Address) envPtrArray, 
  358.                   &newEnvPtrArrayLength, (Address *) &newEnvPtrArray);
  359.     if (newEnvPtrArrayLength == 0) {
  360.         return(SYS_ARG_NOACCESS);
  361.     }
  362.     } else {
  363.     newEnvPtrArray = (char **) NIL;
  364.     newEnvPtrArrayLength = 0;
  365.     }
  366.     /*
  367.      * Perform the exec, if local, or setup the user's stack if remote.
  368.      */
  369.     userArgs.userMode = TRUE;
  370.     userArgs.argPtrArray = newArgPtrArray;
  371.     userArgs.numArgs = newArgPtrArrayLength / sizeof(Address);
  372.     userArgs.argLength = newArgPtrArrayLength;
  373.     userArgs.envPtrArray = newEnvPtrArray;
  374.     userArgs.numEnvs = newEnvPtrArrayLength / sizeof(Address);
  375.     userArgs.envLength = newEnvPtrArrayLength;
  376.  
  377.     /*
  378.      * Check for explicit remote exec onto this host, in which case it's
  379.      * a local exec.
  380.      */
  381.     if (host == rpc_SpriteID) {
  382.     host = 0;
  383.     }
  384.  
  385.     if (host != 0) {
  386.     encapPtrPtr = &encapPtr;
  387.     } else {
  388.     encapPtrPtr = (ExecEncapState **) NIL;
  389.     }
  390.     status = DoExec(execFileName, &userArgs, encapPtrPtr, debugMe);
  391.     if (status == SUCCESS) {
  392.     if (host != 0) {
  393.         /*
  394.          * Set up the process to migrate.
  395.          */
  396.         procPtr = Proc_GetCurrentProc();
  397.         Proc_Lock(procPtr);
  398.         status = ProcInitiateMigration(procPtr, host);
  399.         if (status == SUCCESS) {
  400.         procPtr->remoteExecBuffer = (Address) encapPtr;
  401.         Proc_FlagMigration(procPtr, host, TRUE);
  402.         } else {
  403.         free((Address) encapPtr);
  404.         }
  405.         Proc_Unlock(procPtr);
  406.     } else {
  407.         panic("Proc_Exec: DoExec returned SUCCESS!!!\n");
  408.     }
  409.     }
  410.     return(status);
  411. }
  412.  
  413.  
  414. /*
  415.  *----------------------------------------------------------------------
  416.  *
  417.  * Proc_KernExec --
  418.  *
  419.  *    Do an exec from a kernel process.  This will exec the program and
  420.  *    change the type of process to a user process.
  421.  *
  422.  * Results:
  423.  *    This routine does not return unless an error occurs from DoExec.
  424.  *
  425.  * Side effects:
  426.  *    None.
  427.  *
  428.  *----------------------------------------------------------------------
  429.  */
  430.  
  431. /* 
  432.  * Use the old Proc_KernExec until this gets installed as the sole procExec.c.
  433.  */
  434. int
  435. Proc_KernExec(fileName, argPtrArray)
  436.     char *fileName;
  437.     char **argPtrArray;
  438. {
  439.     register    Proc_ControlBlock    *procPtr;
  440.     ReturnStatus            status;
  441.     UserArgs                userArgs;
  442.  
  443.     procPtr = Proc_GetCurrentProc();
  444.  
  445.     /*
  446.      * Set up dummy segments so that DoExec can work properly.
  447.      */
  448.  
  449.     procPtr->vmPtr->segPtrArray[VM_CODE] = 
  450.                 Vm_SegmentNew(VM_CODE, (Fs_Stream *) NIL, 0,
  451.                               1, 0, procPtr);
  452.     if (procPtr->vmPtr->segPtrArray[VM_CODE] == (Vm_Segment *) NIL) {
  453.     return(PROC_NO_SEGMENTS);
  454.     }
  455.  
  456.     procPtr->vmPtr->segPtrArray[VM_HEAP] =
  457.             Vm_SegmentNew(VM_HEAP, (Fs_Stream *) NIL, 0, 1, 1, procPtr);
  458.     if (procPtr->vmPtr->segPtrArray[VM_HEAP] == (Vm_Segment *) NIL) {
  459.     Vm_SegmentDelete(procPtr->vmPtr->segPtrArray[VM_CODE], procPtr);
  460.     return(PROC_NO_SEGMENTS);
  461.     }
  462.  
  463.     procPtr->vmPtr->segPtrArray[VM_STACK] =
  464.             Vm_SegmentNew(VM_STACK, (Fs_Stream *) NIL, 
  465.                    0 , 1, mach_LastUserStackPage, procPtr);
  466.     if (procPtr->vmPtr->segPtrArray[VM_STACK] == (Vm_Segment *) NIL) {
  467.     Vm_SegmentDelete(procPtr->vmPtr->segPtrArray[VM_CODE], procPtr);
  468.     Vm_SegmentDelete(procPtr->vmPtr->segPtrArray[VM_HEAP], procPtr);
  469.     return(PROC_NO_SEGMENTS);
  470.     }
  471.  
  472.     /*
  473.      * Change this process to a user process.
  474.      */
  475.  
  476.     Proc_Lock(procPtr);
  477.     procPtr->genFlags &= ~PROC_KERNEL;
  478.     procPtr->genFlags |= PROC_USER;
  479.     Proc_Unlock(procPtr);
  480.  
  481.     VmMach_ReinitContext(procPtr);
  482.  
  483.     userArgs.userMode = FALSE;
  484.     userArgs.argPtrArray = argPtrArray;
  485.     userArgs.numArgs = PROC_MAX_EXEC_ARGS;
  486.     userArgs.argLength = PROC_MAX_EXEC_ARGS * sizeof(Address);
  487.     userArgs.envPtrArray = (char **) NIL;
  488.     userArgs.numEnvs = 0;
  489.     userArgs.envLength = 0;
  490.     status = DoExec(fileName, &userArgs, (ExecEncapState **) NIL, FALSE);
  491.     /*
  492.      * If the exec failed, then delete the extra segments and fix up the
  493.      * proc table entry to put us back into kernel mode.
  494.      */
  495.  
  496.     Proc_Lock(procPtr);
  497.     procPtr->genFlags &= ~PROC_USER;
  498.     procPtr->genFlags |= PROC_KERNEL;
  499.     Proc_Unlock(procPtr);
  500.  
  501.     VmMach_ReinitContext(procPtr);
  502.  
  503.     Vm_SegmentDelete(procPtr->vmPtr->segPtrArray[VM_CODE], procPtr);
  504.     Vm_SegmentDelete(procPtr->vmPtr->segPtrArray[VM_HEAP], procPtr);
  505.     Vm_SegmentDelete(procPtr->vmPtr->segPtrArray[VM_STACK], procPtr);
  506.  
  507.     return(status);
  508. }
  509.  
  510.  
  511. /*
  512.  *----------------------------------------------------------------------
  513.  *
  514.  * SetupArgs --
  515.  *
  516.  *    Chase through arrays of character strings (usually in user space)
  517.  *    and copy them into a contiguous array.  This array is later copied
  518.  *    onto the stack of the exec'd program, and it may be used to
  519.  *    pass the arguments to another host for a remote exec.  It
  520.  *    contains argc, argv, envp, and the strings referenced by argv and
  521.  *    envp.  All values in argv and envp are relative to the presumed
  522.  *    start of the data in user space, which is normally set up to end at
  523.  *    mach_MaxUserStackAddr.  If
  524.  *    the exec is performed on a different machine, the pointers in argv and
  525.  *    envp must be adjusted by the relative values of mach_MaxUserStackAddr.
  526.  *
  527.  *    The format of the structure is defined by ExecEncapState above.
  528.  *        
  529.  *
  530.  * Results:
  531.  *    A ReturnStatus is returned.  Any non-SUCCESS result indicates a failure
  532.  *    that should be returned to the user.
  533.  *    In addition, a pointer to the encapsulated stack is returned,
  534.  *    as well as its size.
  535.  *
  536.  * Side effects:
  537.  *    Memory is allocated for the argument stack.
  538.  *
  539.  *----------------------------------------------------------------------
  540.  */
  541.  
  542. static ReturnStatus
  543. SetupArgs(userArgsPtr, extraArgArray, argStackPtr, argStringPtr)
  544.     UserArgs *userArgsPtr;    /* Information for taking args
  545.                  * and environment. */ 
  546.     char     **extraArgArray;    /* Any arguments that should be
  547.                        * inserted prior to argv[1] */
  548.     Address  *argStackPtr;     /* Pointer to contain address of encapsulated
  549.                  * stack. */
  550.     char     **argStringPtr;    /* Pointer to allocated buffer for argument
  551.                  * list as a single string (for ps) */
  552. {
  553.     int         numArgs;        /* The number of arguments in the argArray. */
  554.     int         numEnvs;        /* The number of arguments in the envArray. */
  555.     register    ArgListElement        *argListPtr;
  556.     register    int            argNumber;
  557.     char                **newArgPtrArray;
  558.     char                **newEnvPtrArray;
  559.     List_Links                argList;
  560.     List_Links                envList;
  561.     char                *argBuffer;
  562.     char                *envBuffer;
  563.     register    char            *argString;
  564.     int                    argStringLength;
  565.     ReturnStatus            status;
  566.     int                    usp;
  567.     int                    paddedArgLength;
  568.     int                    paddedEnvLength;
  569.     int                    bufSize;
  570.     Address                buffer;
  571.     int                    stackSize;
  572.     ExecEncapHeader            *hdrPtr;
  573.     ExecEncapState            *encapPtr;
  574.  
  575.     /*
  576.      * Initialize variables so when if we abort we know what to clean up.
  577.      */
  578.     *argStringPtr = (char *) NIL;
  579.     
  580.     List_Init(&argList);
  581.     List_Init(&envList);
  582.  
  583.     /*
  584.      * Copy in the arguments.  argStringLength is an upper bound on
  585.      * the total length permitted.
  586.      */
  587.     numArgs = userArgsPtr->numArgs;
  588.     argStringLength = PROC_MAX_EXEC_ARG_LENGTH;
  589.     status = GrabArgArray(PROC_MAX_EXEC_ARG_LENGTH + 1,
  590.               userArgsPtr->userMode, extraArgArray,
  591.               userArgsPtr->argPtrArray, &numArgs,
  592.               &argList, &argStringLength,
  593.               &paddedArgLength);
  594.  
  595.  
  596.     if (status != SUCCESS) {
  597.     goto execError;
  598.     }
  599.     /*
  600.      * Copy in the environment.
  601.      */
  602.  
  603.     numEnvs = userArgsPtr->numEnvs;
  604.     status = GrabArgArray(PROC_MAX_ENVIRON_LENGTH + 1,
  605.               userArgsPtr->userMode, (char **) NIL,
  606.               userArgsPtr->envPtrArray, &numEnvs,
  607.               &envList, (int *) NIL,
  608.               &paddedEnvLength);
  609.  
  610.     if (status != SUCCESS) {
  611.     goto execError;
  612.     }
  613.  
  614.     /*
  615.      * Now copy all of the arguments and environment variables into a buffer.
  616.      * Allocate the buffer and initialize pointers into it.
  617.      * The stack ends up in the following state:  the top word is argc.
  618.      * Right below this is the array of pointers to arguments (argv).  Right
  619.      * below this is the array of pointers to environment stuff (envp).  So,
  620.      * to figure out the address of argv, one simply adds a word to the address
  621.      * of the top of the stack.  To figure out the address of envp, one
  622.      * looks at argc and skips over the appropriate amount of space to jump
  623.      * over argc and argv = (1 + (argc + 1)) * 4 bytes.  The extra "1" is for
  624.      * the null argument at the end of argv.  Below all that stuff on the
  625.      * stack come the environment and argument strings themselves.
  626.      */
  627.     bufSize = sizeof(ExecEncapState) + (numArgs + numEnvs + 2) * sizeof(Address)
  628.     + paddedArgLength + paddedEnvLength;
  629.     buffer = malloc(bufSize);
  630.     *argStackPtr = buffer;
  631.     encapPtr = (ExecEncapState *) buffer;
  632.     hdrPtr = &encapPtr->hdr;
  633.     hdrPtr->size = bufSize;
  634.     stackSize = Byte_AlignAddr((bufSize - sizeof(ExecEncapHeader)));
  635.     hdrPtr->base = mach_MaxUserStackAddr - stackSize;
  636.     encapPtr->argc = numArgs;
  637.     newArgPtrArray = (char **) (buffer + sizeof(ExecEncapState));
  638.     newEnvPtrArray = (char **) ((int) newArgPtrArray +
  639.                 (numArgs + 1) * sizeof(Address));
  640.     argBuffer = (Address) ((int) newEnvPtrArray +
  641.                (numEnvs + 1) * sizeof(Address));
  642.     envBuffer =  (argBuffer + paddedArgLength);
  643.                 
  644.     argNumber = 0;
  645.     usp = (int)hdrPtr->base + (int) argBuffer - (int) &encapPtr->argc;
  646.     argString = malloc(argStringLength + 1);
  647.     *argStringPtr = argString;
  648.  
  649.     while (!List_IsEmpty(&argList)) {
  650.     argListPtr = (ArgListElement *) List_First(&argList);
  651.     /*
  652.      * Copy the argument.
  653.      */
  654.     bcopy((Address) argListPtr->stringPtr, (Address) argBuffer,
  655.             argListPtr->stringLen);
  656.     newArgPtrArray[argNumber] = (char *) usp;
  657.     argBuffer += Byte_AlignAddr(argListPtr->stringLen);
  658.     usp += Byte_AlignAddr(argListPtr->stringLen);
  659.     bcopy((Address) argListPtr->stringPtr, argString,
  660.             argListPtr->stringLen - 1);
  661.     argString[argListPtr->stringLen - 1] = ' ';
  662.     argString += argListPtr->stringLen;
  663.     /*
  664.      * Clean up
  665.      */
  666.     List_Remove((List_Links *) argListPtr);
  667.     free((Address) argListPtr->stringPtr);
  668.     free((Address) argListPtr);
  669.     argNumber++;
  670.     }
  671.     argString[0] = '\0';
  672.     newArgPtrArray[argNumber] = (char *) USER_NIL;
  673.     
  674.     argNumber = 0;
  675.     while (!List_IsEmpty(&envList)) {
  676.     argListPtr = (ArgListElement *) List_First(&envList);
  677.     /*
  678.      * Copy the environment variable.
  679.      */
  680.     bcopy((Address) argListPtr->stringPtr, (Address) envBuffer,
  681.             argListPtr->stringLen);
  682.     newEnvPtrArray[argNumber] = (char *) usp;
  683.     envBuffer += Byte_AlignAddr(argListPtr->stringLen);
  684.     usp += Byte_AlignAddr(argListPtr->stringLen);
  685.     /*
  686.      * Clean up
  687.      */
  688.     List_Remove((List_Links *) argListPtr);
  689.     free((Address) argListPtr->stringPtr);
  690.     free((Address) argListPtr);
  691.     argNumber++;
  692.     }
  693.     newEnvPtrArray[argNumber] = (char *) USER_NIL;
  694.  
  695.     /*
  696.      * We're done here.  Leave it to the caller to free the copy of the
  697.      * stack after copying it to user space.
  698.      */
  699.     return(SUCCESS);
  700.     
  701. execError:
  702.     /*
  703.      * The exec failed while copying in the arguments.  Free any
  704.      * arguments or environment variables that were copied in.
  705.      */
  706.     while (!List_IsEmpty(&argList)) {
  707.     argListPtr = (ArgListElement *) List_First(&argList);
  708.     List_Remove((List_Links *) argListPtr);
  709.     free((Address) argListPtr->stringPtr);
  710.     free((Address) argListPtr);
  711.     }
  712.     while (!List_IsEmpty(&envList)) {
  713.     argListPtr = (ArgListElement *) List_First(&envList);
  714.     List_Remove((List_Links *) argListPtr);
  715.     free((Address) argListPtr->stringPtr);
  716.     free((Address) argListPtr);
  717.     }
  718.     return(status);
  719.  
  720. }
  721.  
  722.  
  723. /*
  724.  *----------------------------------------------------------------------
  725.  *
  726.  * GrabArgArray --
  727.  *
  728.  *    Copy a an array of strings from user space and put it in a
  729.  *    linked list of strings.  The terminology for "args" refers
  730.  *    to argv, but the same routine is used for environment variables
  731.  *    as well.
  732.  *
  733.  * Results:
  734.  *    A ReturnStatus indicates any sort of error, indicating immediate
  735.  *    failure that should be reported to the user.  Otherwise, the
  736.  *    arguments and their lengths are returned in the linked list
  737.  *    referred to by argListPtr, and the total length is returned
  738.  *    in *totalLengthPtr.
  739.  *
  740.  * Side effects:
  741.  *    Memory is allocated to hold the strings and the structures
  742.  *    pointing to them.
  743.  *
  744.  *----------------------------------------------------------------------
  745.  */
  746.  
  747. static ReturnStatus
  748. GrabArgArray(maxLength, userProc, extraArgArray, argPtrArray, numArgsPtr,
  749.          argList, realLengthPtr, paddedLengthPtr)
  750.     int         maxLength;        /* The maximum length of one argument */
  751.     Boolean  userProc;        /* Set if the calling process is a user 
  752.                       * process. */
  753.     char     **extraArgArray;    /* Any arguments that should be
  754.                        * inserted prior to argv[1] */
  755.     char     **argPtrArray;    /* The array of argument pointers. */
  756.     int         *numArgsPtr;    /* Pointer to the number of arguments in the
  757.                  * argArray. This is updated with the
  758.                  * actual number of arguments. */
  759.     List_Links *argList;    /* Pointer to header of list containing
  760.                  * copied data. Assumed to be initialized by
  761.                  * caller. */
  762.     int      *realLengthPtr;     /* Pointer to contain combined size, without
  763.                  * padding.   Value passed in contains
  764.                  * maximum. */
  765.     int      *paddedLengthPtr;     /* Pointer to contain combined size, including
  766.                  * padding. */
  767. {
  768.     int                 totalLength = 0;
  769.     int                 paddedTotalLength = 0;
  770.     int                 extraArgs;
  771.     Boolean                 accessible;
  772.     register    ArgListElement        *argListPtr;
  773.     register    char            **argPtr;
  774.     register    int            argNumber;
  775.     ReturnStatus            status;
  776.     char                *stringPtr;
  777.     int                    stringLength;
  778.     int                    realLength;
  779.     
  780.     if (extraArgArray != (char **) NIL) {
  781.     for (extraArgs = 0; extraArgArray[extraArgs] != (char *)NIL;
  782.          extraArgs++) {
  783.     }
  784.     } else {
  785.     extraArgs = 0;
  786.     }
  787.     
  788.     for (argNumber = 0, argPtr = argPtrArray; 
  789.      argNumber < *numArgsPtr;
  790.      argNumber++) {
  791.  
  792.     accessible = FALSE;
  793.  
  794.     if ((argNumber > 0 || argPtrArray == (char **) NIL) && extraArgs > 0) {
  795.         stringPtr = extraArgArray[0];
  796.         realLength = strlen(stringPtr) + 1;
  797.         extraArgArray++;
  798.         extraArgs--;
  799.     } else {
  800.         if (!userProc) {
  801.         if (*argPtr == (char *) NIL) {
  802.             break;
  803.         }
  804.         stringPtr = *argPtr;
  805.         stringLength = maxLength;
  806.         } else {
  807.         if (*argPtr == (char *) USER_NIL) {
  808.             break;
  809.         }
  810.         Vm_MakeAccessible(VM_READONLY_ACCESS,
  811.                   maxLength + 1, 
  812.                   (Address) *argPtr, 
  813.                   &stringLength,
  814.                   (Address *) &stringPtr);
  815.         if (stringLength == 0) {
  816.             status = SYS_ARG_NOACCESS;
  817.             goto execError;
  818.         }
  819.         accessible = TRUE;
  820.         }
  821.         /*
  822.          * Find out the length of the argument.  Because of accessibility
  823.          * limitations the whole string may not be available.
  824.          */
  825.         {
  826.         register char *charPtr;
  827.         for (charPtr = stringPtr, realLength = 0;
  828.              (realLength < stringLength) && (*charPtr != '\0');
  829.              charPtr++, realLength++) {
  830.         }
  831.         realLength++;
  832.         }
  833.         /*
  834.          * Move to the next argument.
  835.          */
  836.         argPtr++;
  837.     }
  838.  
  839.     /*
  840.      * Put this string onto the argument list.
  841.      */
  842.     argListPtr = (ArgListElement *)
  843.         malloc(sizeof(ArgListElement));
  844.     argListPtr->stringPtr =  malloc(realLength);
  845.     argListPtr->stringLen = realLength;
  846.     List_InitElement((List_Links *) argListPtr);
  847.     List_Insert((List_Links *) argListPtr, LIST_ATREAR(argList));
  848.     /*
  849.      * Calculate the room on the stack needed for this string.
  850.      * Make it double-word aligned to make access efficient on
  851.      * all machines.  Increment the amount needed to save the argument
  852.      * list (the same total length, but without the padding).
  853.      */
  854.     paddedTotalLength += Byte_AlignAddr(realLength);
  855.     totalLength += realLength;
  856.     /*
  857.      * Copy over the argument and ensure null termination.
  858.      */
  859.     bcopy((Address) stringPtr, (Address) argListPtr->stringPtr, realLength);
  860.     argListPtr->stringPtr[realLength-1] = '\0';
  861.     /*
  862.      * Clean up 
  863.      */
  864.     if (accessible) {
  865.         Vm_MakeUnaccessible((Address) stringPtr, stringLength);
  866.     }
  867.     if (realLength > maxLength+1) {
  868.         status = GEN_E2BIG;
  869.         goto execError;
  870.     }
  871.     }
  872.     if (realLengthPtr != (int *) NIL) {
  873.     if (totalLength > *realLengthPtr) {
  874.         /*
  875.          * Would really like to flag "argument too long" here.
  876.          * Also, should we check after every argument?
  877.          */
  878.         status = GEN_INVALID_ARG;
  879.         goto execError;
  880.     }
  881.     *realLengthPtr = totalLength;
  882.     }
  883.     if (paddedLengthPtr != (int *) NIL) {
  884.     *paddedLengthPtr = paddedTotalLength;
  885.     }
  886.     *numArgsPtr = argNumber;
  887.     return(SUCCESS);
  888.     
  889. execError:
  890.     /*
  891.      * We hit an error while copying in the arguments.  Free any
  892.      * arguments that were copied in.
  893.      */
  894.     while (!List_IsEmpty(argList)) {
  895.     argListPtr = (ArgListElement *) List_First(argList);
  896.     List_Remove((List_Links *) argListPtr);
  897.     free((Address) argListPtr->stringPtr);
  898.     free((Address) argListPtr);
  899.     }
  900.     return(status);
  901. }
  902.  
  903.  
  904. /*
  905.  *----------------------------------------------------------------------
  906.  *
  907.  * DoExec --
  908.  *
  909.  *    Exec a new program.  If the exec is to be done on this host, the
  910.  *    current process image is overlayed by the 
  911.  *    newly exec'd program.  If not, then set up the image of the
  912.  *    user stack and set *encapPtrPtr to point to it.
  913.  *
  914.  * Results:
  915.  *    In the local case, this routine does not return unless an
  916.  *    error occurs in which case the
  917.  *    error code is returned.  In the remote case, SUCCESS indicates
  918.  *    the remote exec may continue.
  919.  *
  920.  * Side effects:
  921.  *    The state of the calling process is modified for the new image and
  922.  *    the argPtrArray and envPtrArray are made unaccessible if this
  923.  *    is a user process.
  924.  *
  925.  *----------------------------------------------------------------------
  926.  */
  927.  
  928. static ReturnStatus
  929. DoExec(fileName, userArgsPtr, encapPtrPtr, debugMe)
  930.     char    fileName[];    /* The name of the file that is to be exec'd */
  931.     UserArgs *userArgsPtr;    /* Information for taking args
  932.                  * and environment, or NIL. */
  933.     ExecEncapState
  934.     **encapPtrPtr;        /* User stack state, either for us to use,
  935.                  * for us to set, or NIL */
  936.     Boolean    debugMe;    /* TRUE means that the process is to be 
  937.                  * sent a SIG_DEBUG signal before
  938.                      * executing its first instruction. */
  939. {
  940.     register    Proc_ControlBlock    *procPtr;
  941.     Vm_ExecInfo                *execInfoPtr;
  942.     Vm_ExecInfo                execInfo;
  943.     Vm_Segment                *codeSegPtr = (Vm_Segment *) NIL;
  944.     char                *argString = (char *) NIL;
  945.     char                *argStringSave;
  946.     Address                argBuffer = (Address) NIL;
  947.     Fs_Stream                *filePtr;
  948.     ReturnStatus            status;
  949.     char                buffer[PROC_MAX_INTERPRET_SIZE];
  950.     Boolean                interpreted = FALSE;
  951.     char                *interpName;
  952.     char                *interpFlags;
  953.     char                *interpArgs[MAX_INTERP_ARGS];
  954.     int                    argBytes;
  955.     Address                userStackPointer;
  956.     Boolean                usedFile;
  957.     int                    uid = -1;
  958.     int                    gid = -1;
  959.     ExecEncapState            *encapPtr;
  960.     int                    importing = 0;
  961.     int                    exporting = 0;
  962.     ProcObjInfo                objInfo;
  963.  
  964. #ifdef notdef
  965.     DBG_CALL;
  966. #endif
  967.  
  968.     /*
  969.      * Use the encapsulation buffer and arguments arrays to determine
  970.      * whether everything is local, or we're starting a remote exec,
  971.      * or finishing one from another host.
  972.      */
  973.     if (encapPtrPtr != (ExecEncapState **) NIL) {
  974.     if (userArgsPtr != (UserArgs *) NIL) {
  975.         exporting = TRUE;
  976.     } else {
  977.         importing = TRUE;
  978.     }
  979.     }
  980.     procPtr = Proc_GetActualProc();
  981.  
  982.     /*
  983.      * objInfo.unixCompat is set if the header of the file indicates
  984.      * it is a Unix binary.
  985.      */
  986.     objInfo.unixCompat = 0;
  987.     procPtr->unixProgress = PROC_PROGRESS_NOT_UNIX;
  988.  
  989.     /* Turn off profiling */
  990.     if (procPtr->Prof_Scale != 0) {
  991.     Prof_Disable(procPtr);
  992.     }
  993.  
  994.     /*
  995.      * Save the argString away, because if we hit an error we always
  996.      * set procPtr->argString back to this value.
  997.      */
  998.     argStringSave = procPtr->argString;
  999.  
  1000.     /*
  1001.      * Open the file that is to be exec'd.
  1002.      */
  1003.     filePtr = (Fs_Stream *) NIL;
  1004.     status =  Fs_Open(fileName, FS_EXECUTE | FS_FOLLOW, FS_FILE, 0, &filePtr);
  1005.     if (status != SUCCESS) {
  1006.     filePtr = (Fs_Stream *) NIL;
  1007.     goto execError;
  1008.     }
  1009.  
  1010.     /*
  1011.      * Determine if this file has the set uid or set gid bits set.
  1012.      */
  1013.     Fs_CheckSetID(filePtr, &uid, &gid);
  1014.  
  1015.     /*
  1016.      * See if this file is already cached by the virtual memory system.
  1017.      */
  1018.     execInfoPtr = (Vm_ExecInfo *)NIL;
  1019.     codeSegPtr = Vm_FindCode(filePtr, procPtr, &execInfoPtr, &usedFile);
  1020.     if (codeSegPtr == (Vm_Segment *) NIL) {
  1021.     int    sizeRead;
  1022.  
  1023.     /*
  1024.      * Read the file header.
  1025.      */
  1026.     sizeRead = PROC_MAX_INTERPRET_SIZE > sizeof(ProcExecHeader) ?
  1027.                         PROC_MAX_INTERPRET_SIZE :
  1028.                         sizeof(ProcExecHeader);
  1029.     status = Fs_Read(filePtr, buffer, 0, &sizeRead);
  1030.     if (status != SUCCESS) {
  1031.         goto execError;
  1032.     }
  1033.     if (sizeRead >= 2 && buffer[0] == '#' && buffer[1] == '!') {
  1034.         Vm_InitCode(filePtr, (Vm_Segment *) NIL, (Vm_ExecInfo *) NIL);
  1035.         /*
  1036.          * See if this is an interpreter file.
  1037.          */
  1038.         status = SetupInterpret(buffer, sizeRead, &filePtr, 
  1039.                     &interpName, &interpFlags, &objInfo); 
  1040.         if (status != SUCCESS) {
  1041.         filePtr = (Fs_Stream *)NIL;
  1042.         goto execError;
  1043.         }
  1044.         interpreted = TRUE;
  1045.         codeSegPtr = Vm_FindCode(filePtr, procPtr, &execInfoPtr, &usedFile);
  1046.     } else {
  1047.         if (sizeRead < sizeof(ProcExecHeader) ||
  1048.         ProcGetObjInfo(filePtr, (ProcExecHeader *)buffer, &objInfo) != SUCCESS) {
  1049.             if(ProcIsObj(filePtr,1)==SUCCESS) {
  1050.             status = GEN_EINVAL;
  1051.             } else {
  1052.             /* Check if it's not an ascii file. */
  1053.             int i;
  1054.             status = PROC_BAD_AOUT_FORMAT;
  1055.             for (i=0;i<sizeRead;i++) {
  1056.                 if (buffer[i]&0x80) {
  1057.                 status = GEN_EINVAL;
  1058.                 printf("Proc_Exec: can't run data file\n");
  1059.                 break;
  1060.                 }
  1061.             }
  1062.             }
  1063.         goto execError;
  1064.         }
  1065.     }
  1066.     }
  1067.  
  1068.     if (!importing) {
  1069.     /*
  1070.      * Set up whatever special arguments we might have due to an
  1071.      * interpreter file.
  1072.      */
  1073.     if (interpreted) {
  1074.         int index = 0;    /* index into array of interpreter args */
  1075.  
  1076.         if (userArgsPtr->argPtrArray == (char **) NIL) {
  1077.         interpArgs[index] = fileName;
  1078.         ++index;
  1079.         }
  1080.         if (interpFlags != (char *)NIL) {
  1081.         interpArgs[index] = interpFlags;
  1082.         ++index;
  1083.         }
  1084.         interpArgs[index] = fileName;
  1085.         ++index;
  1086.         interpArgs[index] = (char *) NIL;
  1087.         if (index >= MAX_INTERP_ARGS) {
  1088.         panic("DoExec: need bigger array for interpreter args.\n");
  1089.         }
  1090.     } 
  1091.     /*
  1092.      * Copy in the argument list and environment into a single contiguous
  1093.      * buffer.
  1094.      */
  1095.     status = SetupArgs(userArgsPtr,
  1096.                (interpreted ? interpArgs : (char **)NIL),
  1097.                &argBuffer, &argString);
  1098.  
  1099.     if (status != SUCCESS) {
  1100.         goto execError;
  1101.     }
  1102.  
  1103.     /*
  1104.      * We no longer need access to the old arguments or the environment. 
  1105.      */
  1106.     if (userArgsPtr->userMode) {
  1107.         if (userArgsPtr->argPtrArray != (char **) NIL) {
  1108.         Vm_MakeUnaccessible((Address) userArgsPtr->argPtrArray,
  1109.                     userArgsPtr->argLength);
  1110.         userArgsPtr->argPtrArray = (char **)NIL;
  1111.         userArgsPtr->argLength = 0;
  1112.         }
  1113.         if (userArgsPtr->envPtrArray != (char **) NIL) {
  1114.         Vm_MakeUnaccessible((Address) userArgsPtr->envPtrArray,
  1115.                     userArgsPtr->envLength);
  1116.         userArgsPtr->envPtrArray = (char **)NIL;
  1117.         userArgsPtr->envLength = 0;
  1118.         }
  1119.     }
  1120.  
  1121.     /*
  1122.      * Close any streams that have been marked close-on-exec.
  1123.      */
  1124.     Fs_CloseOnExec(procPtr);
  1125.     } else {
  1126.     /*
  1127.      * We're "importing" this process.  Use the stack copied over from
  1128.      * its former host.
  1129.      */
  1130.     argBuffer = procPtr->remoteExecBuffer;
  1131.     procPtr->remoteExecBuffer = (Address) NIL;
  1132.     encapPtr = (ExecEncapState *) argBuffer;
  1133.     argString = encapPtr->hdr.argString;
  1134.     }
  1135.     
  1136.     /*
  1137.      * Change the argument string.
  1138.      */
  1139.     procPtr->argString = argString;
  1140.     /*
  1141.      * Do set uid here.  This way, the uid will be set before a remote
  1142.      * exec.
  1143.      */
  1144.     if (uid != -1) {
  1145.     procPtr->effectiveUserID = uid;
  1146.     }
  1147.     /*
  1148.      * If we're doing the initial part of a remote exec, time to
  1149.      * return to our caller.  Free up whatever virtual memory resources
  1150.      * we had set up.
  1151.      */
  1152.     encapPtr = (ExecEncapState *) argBuffer;
  1153.     if (exporting) {
  1154.     if (filePtr != (Fs_Stream *) NIL) {
  1155.         if (codeSegPtr != (Vm_Segment *) NIL) {
  1156.         Vm_SegmentDelete(codeSegPtr, procPtr);
  1157.         if (!usedFile) {
  1158.             /*
  1159.              * If usedFile is TRUE then the file has already been closed
  1160.              * by Vm_SegmentDelete.
  1161.              */
  1162.             (void) Fs_Close(filePtr);
  1163.         }
  1164.         } else {
  1165.         /*
  1166.          * We're not setting up the segment after all, so let vm
  1167.          * clean up state and wake up anyone waiting for us to
  1168.          * set up the segment.
  1169.          */
  1170.         Vm_InitCode(filePtr, (Vm_Segment *) NIL, (Vm_ExecInfo *) NIL);
  1171.         (void) Fs_Close(filePtr);
  1172.         }
  1173.     }
  1174.     *encapPtrPtr = encapPtr;
  1175.     encapPtr->hdr.fileName = fileName;
  1176.     encapPtr->hdr.argString = argString;
  1177.     return(SUCCESS);
  1178.     }
  1179.     /*
  1180.      * The file name has been dynamically allocated if it was copied in
  1181.      * on this host from user space.
  1182.      */
  1183.     if (!importing && userArgsPtr->userMode) {
  1184.     free(fileName);
  1185.     fileName = (char *) NIL;
  1186.     }
  1187.     /*
  1188.      * Set up virtual memory for the new image.
  1189.      */
  1190.     if (execInfoPtr == (Vm_ExecInfo *)NIL) {
  1191.     execInfoPtr = &execInfo;
  1192.     }
  1193.     if (!SetupVM(procPtr, &objInfo, filePtr, usedFile, &codeSegPtr, 
  1194.          execInfoPtr)) {
  1195.     /*
  1196.      * Setup VM will make sure that the file is closed and that
  1197.      * all new segments are freed up.
  1198.      */
  1199.     filePtr = (Fs_Stream *) NIL;
  1200.     status = VM_NO_SEGMENTS;
  1201.     goto execError;
  1202.     }
  1203.  
  1204.     /*
  1205.      * Now copy all of the arguments and environment variables onto the stack.
  1206.      */
  1207.     argBytes = encapPtr->hdr.size - sizeof(ExecEncapHeader);
  1208.     userStackPointer = encapPtr->hdr.base;
  1209.     status = Vm_CopyOut(argBytes, (Address) &encapPtr->argc,
  1210.               userStackPointer);
  1211.  
  1212.     if (status != SUCCESS) {
  1213.     goto execError;
  1214.     }
  1215.  
  1216.     /*
  1217.      * Free original argString (kept in argStringSave, in case we
  1218.      * needed it) here, after last chance to goto execError.
  1219.      */
  1220.     if (argStringSave != (char *)NIL) {
  1221.     free(argStringSave);
  1222.     }
  1223.  
  1224.     /*
  1225.      * Set-gid only needs to be done on the host running the process.
  1226.      */
  1227.     if (gid != -1) {
  1228.     ProcAddToGroupList(procPtr, gid);
  1229.     }
  1230.  
  1231.     /*
  1232.      * Take signal actions for execed process.
  1233.      */
  1234.     Sig_Exec(procPtr);
  1235.     if (debugMe) {
  1236.     /*
  1237.      * Debugged processes get a SIG_DEBUG at start up.
  1238.      */
  1239.     Sig_SendProc(procPtr, SIG_DEBUG, SIG_NO_CODE, (Address)0);
  1240.     }
  1241.     if (!importing && (procPtr->genFlags & PROC_FOREIGN)) {
  1242.     ProcRemoteExec(procPtr, uid);
  1243.     }
  1244.  
  1245.     /* If this is a vfork process, wake the parent now */
  1246.     if (procPtr->genFlags & PROC_VFORKCHILD) {
  1247.     Proc_VforkWakeup(procPtr);
  1248.     }
  1249.  
  1250.     Proc_Unlock(procPtr);
  1251.  
  1252.     free(argBuffer);
  1253.     argBuffer = (Address) NIL;
  1254.     
  1255.     /*
  1256.      * Move the stack pointer on the sun4.
  1257.      */
  1258.     if (execInfoPtr->flags & UNIX_CODE) {
  1259. #ifdef sun4
  1260.     /*
  1261.      * Unix on the sun4 has the stack in a different location from
  1262.      * Sprite.
  1263.      */
  1264.     userStackPointer += 32;
  1265.     if (debugProcStubs) {
  1266.         printf("Moving stack pointer for Unix binary.\n");
  1267.     }
  1268. #endif
  1269.     procPtr->unixProgress = PROC_PROGRESS_UNIX;
  1270.     }
  1271.  
  1272.     /*
  1273.      * Disable interrupts.  Note that we don't use the macro DISABLE_INTR 
  1274.      * because there is an implicit enable interrupts when we return to user 
  1275.      * mode.
  1276.      */
  1277.     Mach_ExecUserProc(procPtr, userStackPointer, (Address) execInfoPtr->entry);
  1278.     panic("DoExec: Proc_RunUserProc returned.\n");
  1279.  
  1280. execError:
  1281.     /*
  1282.      * The exec failed after or while copying in the arguments.  Free any
  1283.      * virtual memory allocated and free any arguments or environment
  1284.      * variables that were copied in.
  1285.      */
  1286.     if (filePtr != (Fs_Stream *) NIL) {
  1287.     if (codeSegPtr != (Vm_Segment *) NIL) {
  1288.         Vm_SegmentDelete(codeSegPtr, procPtr);
  1289.         if (!usedFile) {
  1290.         /*
  1291.          * If usedFile is TRUE then the file has already been closed
  1292.          * by Vm_SegmentDelete.
  1293.          */
  1294.         (void) Fs_Close(filePtr);
  1295.         }
  1296.     } else {
  1297.         Vm_InitCode(filePtr, (Vm_Segment *) NIL, (Vm_ExecInfo *) NIL);
  1298.         (void) Fs_Close(filePtr);
  1299.     }
  1300.     }
  1301.     if (userArgsPtr != (UserArgs *) NIL && userArgsPtr->userMode) {
  1302.     if (userArgsPtr->argPtrArray != (char **) NIL) {
  1303.         Vm_MakeUnaccessible((Address) userArgsPtr->argPtrArray,
  1304.                 userArgsPtr->argLength);
  1305.         userArgsPtr->argPtrArray = (char **)NIL;
  1306.         userArgsPtr->argLength = 0;
  1307.     }
  1308.     if (userArgsPtr->envPtrArray != (char **) NIL) {
  1309.         Vm_MakeUnaccessible((Address) userArgsPtr->envPtrArray,
  1310.                 userArgsPtr->envLength);
  1311.         userArgsPtr->envPtrArray = (char **)NIL;
  1312.         userArgsPtr->envLength = 0;
  1313.     }
  1314.     }
  1315.     if (argBuffer != (Address) NIL) {
  1316.     free(argBuffer);
  1317.     }
  1318.     if (argString != (Address) NIL) {
  1319.     free(argString);
  1320.     }
  1321.     /*
  1322.      * Restore original arg string.  If we don't do this, then when
  1323.      * DoFork() tries to free() the arg string (after this process
  1324.      * exits, when some other process gets the then-empty process
  1325.      * slot), free() will panic because the original argString was
  1326.      * just freed above.
  1327.      */
  1328.     procPtr->argString = argStringSave;
  1329.  
  1330.     if (!importing && (fileName != (char *) NIL) && userArgsPtr->userMode) {
  1331.     free(fileName);
  1332.     fileName = (char *) NIL;
  1333.     }
  1334.     return(status);
  1335. }
  1336.  
  1337.  
  1338. /*
  1339.  *----------------------------------------------------------------------
  1340.  *
  1341.  * SetupInterpret --
  1342.  *
  1343.  *    Read in the interpreter name, arguments and object file header.
  1344.  *
  1345.  * Results:
  1346.  *    Error if for some reason could not parse the interpreter name
  1347.  *    and arguments are could not open the interpreter object file.
  1348.  *
  1349.  * Side effects:
  1350.  *    *filePtrPtr contains pointer to the interpreter object file, 
  1351.  *    *argPtrPtr points to interpreter argument string, *extraArgsPtr
  1352.  *    contains number of arguments that have to be prepended to the 
  1353.  *    argument vector passed to the interpreter and *aoutPtr contains the
  1354.  *    interpreter files a.out header.
  1355.  *
  1356.  *----------------------------------------------------------------------
  1357.  */ 
  1358.  
  1359. static ReturnStatus
  1360. SetupInterpret(buffer, sizeRead, filePtrPtr, interpNamePtr, 
  1361.            interpFlagsPtr, objInfoPtr)
  1362.     register    char    *buffer;    /* Bytes read in from file.*/
  1363.     int            sizeRead;    /* Number of bytes in buffer. */    
  1364.     register    Fs_Stream **filePtrPtr;    /* IN/OUT parameter: Exec'd file as 
  1365.                      * input, interpreter file as output. */
  1366.     char        **interpNamePtr; /* OUT: name of interpreter file. */
  1367.     char        **interpFlagsPtr;/* OUT: single flags string to 
  1368.                       * pass to interpreter, possibly 
  1369.                       * NIL */ 
  1370.     ProcObjInfo        *objInfoPtr;    /* Place to put obj file info. */
  1371. {
  1372.     register    char    *strPtr;
  1373.     char        *interpName; /* name of the interpreter */
  1374.     int            i;
  1375.     ReturnStatus    status;
  1376.     ProcExecHeader    execHeader;
  1377.  
  1378.     (void) Fs_Close(*filePtrPtr);
  1379.  
  1380.     /*
  1381.      * Make sure the interpreter name and arguments are terminated by a 
  1382.      * carriage return.
  1383.      */
  1384.     for (i = 2, strPtr = &(buffer[2]);
  1385.      i < sizeRead && *strPtr != '\n';
  1386.      i++, strPtr++) {
  1387.     }
  1388.     if (i == sizeRead) {
  1389.     return(PROC_BAD_FILE_NAME);
  1390.     }
  1391.     *strPtr = '\0';
  1392.  
  1393.     /*
  1394.      * Get a pointer to the name of the file to exec.
  1395.      */
  1396.  
  1397.     for (strPtr = &(buffer[2]); isspace(*strPtr); strPtr++) {
  1398.     }
  1399.     if (*strPtr == '\0') {
  1400.     return(PROC_BAD_FILE_NAME);
  1401.     }
  1402.     interpName = strPtr;
  1403.     *interpNamePtr = interpName;
  1404.     while (!isspace(*strPtr) && *strPtr != '\0') {
  1405.     strPtr++;
  1406.     }
  1407.  
  1408.     /*
  1409.      * Get a pointer to the arguments if there are any.
  1410.      */
  1411.  
  1412.     *interpFlagsPtr = (char *)NIL;
  1413.  
  1414.     if (*strPtr != '\0') {
  1415.     *strPtr = '\0';
  1416.     strPtr++;
  1417.     while (isspace(*strPtr)) {
  1418.         strPtr++;
  1419.     }
  1420.     if (*strPtr != '\0') {
  1421.         *interpFlagsPtr = strPtr;
  1422.     }
  1423.     }
  1424.  
  1425.     /*
  1426.      * Open the interpreter to exec and read the a.out header.
  1427.      */
  1428.  
  1429.     status = Fs_Open(interpName, FS_EXECUTE | FS_FOLLOW, FS_FILE, 0,
  1430.              filePtrPtr);
  1431.     if (status != SUCCESS) {
  1432.     return(status);
  1433.     }
  1434.  
  1435.     sizeRead = sizeof(ProcExecHeader);
  1436.     status = Fs_Read(*filePtrPtr, (Address)&execHeader, 0, &sizeRead);
  1437.     if (status == SUCCESS && sizeRead != sizeof(ProcExecHeader)) {
  1438.     status = PROC_BAD_AOUT_FORMAT;
  1439.     } else {
  1440.     status = ProcGetObjInfo(*filePtrPtr, &execHeader, objInfoPtr);
  1441.     }
  1442.     if (status != SUCCESS) {
  1443.     if(ProcIsObj(*filePtrPtr,1)==SUCCESS) {
  1444.         status = GEN_EINVAL;
  1445.     } else {
  1446.         status = PROC_BAD_AOUT_FORMAT;
  1447.     }
  1448.     (void) Fs_Close(*filePtrPtr);
  1449.     }
  1450.     return(status);
  1451. }
  1452.  
  1453. /*
  1454.  *----------------------------------------------------------------------
  1455.  *
  1456.  * SetupVM --
  1457.  *
  1458.  *    Setup virtual memory for this process.
  1459.  *
  1460.  * Results:
  1461.  *    TRUE if could set up VM, false otherwise.
  1462.  *
  1463.  * Side effects:
  1464.  *    *filePtrPtr contains pointer to the interpreter object file, 
  1465.  *    *argPtrPtr points to interpreter argument string, *extraArgsPtr
  1466.  *    contains number of arguments that have to be prepended to the 
  1467.  *    argument vector passed to the interpreter and *aoutPtr contains the
  1468.  *    interpreter files a.out header.
  1469.  *
  1470.  *----------------------------------------------------------------------
  1471.  */ 
  1472. static Boolean
  1473. SetupVM(procPtr, objInfoPtr, codeFilePtr, usedFile, codeSegPtrPtr, execInfoPtr)
  1474.     register    Proc_ControlBlock    *procPtr;
  1475.     register    ProcObjInfo        *objInfoPtr;
  1476.     Fs_Stream                *codeFilePtr;
  1477.     Boolean                usedFile;
  1478.     Vm_Segment                **codeSegPtrPtr;
  1479.     register    Vm_ExecInfo        *execInfoPtr;
  1480. {
  1481.     register    Vm_Segment    *segPtr;
  1482.     int                numPages;
  1483.     int                fileOffset;
  1484.     int                pageOffset;
  1485.     Boolean            notFound;
  1486.     Vm_Segment            *heapSegPtr;
  1487.     Fs_Stream            *heapFilePtr;
  1488.     Address            heapEnd = (Address) NIL;
  1489.     int                realCode = 1;
  1490.  
  1491.     if (*codeSegPtrPtr == (Vm_Segment *) NIL) {
  1492.     if (objInfoPtr->unixCompat) {
  1493.         execInfoPtr->flags = UNIX_CODE;
  1494.     } else {
  1495.         execInfoPtr->flags = 0;
  1496.     }
  1497.     execInfoPtr->entry = (int)objInfoPtr->entry;
  1498.     if (objInfoPtr->heapSize != 0) {
  1499.         execInfoPtr->heapPages = 
  1500.             (objInfoPtr->heapSize - 1) / vm_PageSize + 1;
  1501.     } else { 
  1502.         execInfoPtr->heapPages = 0;
  1503.     }
  1504.     if (objInfoPtr->bssSize != 0) {
  1505.         execInfoPtr->heapPages += 
  1506.             (objInfoPtr->bssSize - 1) / vm_PageSize + 1;
  1507.     }
  1508.     execInfoPtr->heapPageOffset = 
  1509.             (unsigned)objInfoPtr->heapLoadAddr / vm_PageSize;
  1510.     execInfoPtr->heapFileOffset = objInfoPtr->heapFileOffset;
  1511.     heapEnd = objInfoPtr->heapLoadAddr + objInfoPtr->heapSize;
  1512.     execInfoPtr->heapExcess =
  1513.         vm_PageSize - ((unsigned)heapEnd&(vm_PageSize-1));
  1514.     if (execInfoPtr->heapExcess == vm_PageSize) {
  1515.         execInfoPtr->heapExcess = 0;
  1516.     }
  1517.     execInfoPtr->bssFirstPage = 
  1518.             (unsigned)objInfoPtr->bssLoadAddr / vm_PageSize;
  1519.     if ((unsigned)(heapEnd-1) / vm_PageSize >= execInfoPtr->bssFirstPage) {
  1520.         /*
  1521.          * End of heap, start of bss in same page, so move bss.
  1522.          */
  1523.         execInfoPtr->bssFirstPage = (unsigned)(heapEnd-1)/vm_PageSize + 1;
  1524.     }
  1525.  
  1526.     if (objInfoPtr->bssSize != 0) {
  1527.         execInfoPtr->bssLastPage = (int) (execInfoPtr->bssFirstPage + 
  1528.                    (objInfoPtr->bssSize - 1) / vm_PageSize);
  1529.     } else {
  1530.         execInfoPtr->bssLastPage = 0;
  1531.     }
  1532.     /* 
  1533.      * Set up the code image.
  1534.      */
  1535.     if (objInfoPtr->codeSize == 0) {
  1536.         /*
  1537.          * Things work better if we have a code segment.
  1538.          * I'm not sure setting realCode=1 is the right thing, but
  1539.          * I'll try it.  If realCode=0 we may have problems when we
  1540.          * try to clean up the file handle.
  1541.          */
  1542.         realCode = 1;
  1543.         objInfoPtr->codeSize = vm_PageSize;
  1544.     }
  1545.     numPages = (objInfoPtr->codeSize - 1) / vm_PageSize + 1;
  1546.     fileOffset = objInfoPtr->codeFileOffset;
  1547.     pageOffset = (unsigned)objInfoPtr->codeLoadAddr / vm_PageSize;
  1548.     segPtr = Vm_SegmentNew(VM_CODE, codeFilePtr, fileOffset,
  1549.                    numPages, pageOffset, procPtr);
  1550.     if (segPtr == (Vm_Segment *) NIL) {
  1551.         Vm_InitCode(codeFilePtr, (Vm_Segment *) NIL, (Vm_ExecInfo *) NIL);
  1552.         (void) Fs_Close(codeFilePtr);
  1553.         return(FALSE);
  1554.     }
  1555.     Vm_ValidatePages(segPtr, pageOffset, pageOffset + numPages - 1,
  1556.              FALSE, TRUE);
  1557.     if (realCode) {
  1558.         Vm_InitCode(codeFilePtr, segPtr, execInfoPtr);
  1559.     } else {
  1560.         Vm_InitCode(codeFilePtr, (Vm_Segment *) NIL, (Vm_ExecInfo *) NIL);
  1561.     }
  1562.     *codeSegPtrPtr = segPtr;
  1563.     notFound = TRUE;
  1564.     } else {
  1565.     notFound = FALSE;
  1566.     }
  1567.  
  1568.     if (usedFile || notFound) {
  1569.     Fsio_StreamCopy(codeFilePtr, &heapFilePtr);
  1570.     } else {
  1571.     heapFilePtr = codeFilePtr;
  1572.     }
  1573.     /* 
  1574.      * Set up the heap image.
  1575.      */
  1576.     segPtr = Vm_SegmentNew(VM_HEAP, heapFilePtr, execInfoPtr->heapFileOffset,
  1577.                    execInfoPtr->heapPages, 
  1578.                    execInfoPtr->heapPageOffset, procPtr);
  1579.     if (segPtr == (Vm_Segment *) NIL) {
  1580.     Vm_SegmentDelete(*codeSegPtrPtr, procPtr);
  1581.     (void) Fs_Close(heapFilePtr);
  1582.     return(FALSE);
  1583.     }
  1584.     Vm_ValidatePages(segPtr, execInfoPtr->heapPageOffset,
  1585.              execInfoPtr->bssFirstPage - 1, FALSE, TRUE);
  1586.     if (execInfoPtr->bssLastPage > 0) {
  1587.     Vm_ValidatePages(segPtr, execInfoPtr->bssFirstPage,
  1588.              execInfoPtr->bssLastPage, TRUE, TRUE);
  1589.     }
  1590.     heapSegPtr = segPtr;
  1591.     /*
  1592.      * Set up a new stack.
  1593.      */
  1594.     segPtr = Vm_SegmentNew(VM_STACK, (Fs_Stream *) NIL, 0, 
  1595.                1, mach_LastUserStackPage, procPtr);
  1596.     if (segPtr == (Vm_Segment *) NIL) {
  1597.     Vm_SegmentDelete(*codeSegPtrPtr, procPtr);
  1598.     Vm_SegmentDelete(heapSegPtr, procPtr);
  1599.     return(FALSE);
  1600.     }
  1601.     Vm_ValidatePages(segPtr, mach_LastUserStackPage, 
  1602.             mach_LastUserStackPage, TRUE, TRUE);
  1603.  
  1604.     Proc_Lock(procPtr);
  1605.     procPtr->genFlags |= PROC_NO_VM;
  1606. #ifdef sun4
  1607.     Mach_FlushWindowsToStack();
  1608.     VmMach_FlushCurrentContext();
  1609. #endif
  1610.     Vm_SegmentDelete(procPtr->vmPtr->segPtrArray[VM_CODE], procPtr);
  1611.     Vm_SegmentDelete(procPtr->vmPtr->segPtrArray[VM_HEAP], procPtr);
  1612.     Vm_SegmentDelete(procPtr->vmPtr->segPtrArray[VM_STACK], procPtr);
  1613.     procPtr->vmPtr->segPtrArray[VM_CODE] = *codeSegPtrPtr;
  1614.     procPtr->vmPtr->segPtrArray[VM_HEAP] = heapSegPtr;
  1615.     procPtr->vmPtr->segPtrArray[VM_STACK] = segPtr;
  1616.     procPtr->genFlags &= ~PROC_NO_VM;
  1617.     VmMach_ReinitContext(procPtr);
  1618.  
  1619.     /*
  1620.      * If heap does not match page boundary, prefetch the partial page
  1621.      * if necessary, and zero the rest.
  1622.      */
  1623.     if (execInfoPtr->heapExcess != 0) {
  1624.     if (realCode && (execInfoPtr->flags & UNIX_CODE) == 0) {
  1625.         printf("SetupVM: Warning: Program %s has unaligned heap %s\n",
  1626.             Fsutil_HandleName(&codeFilePtr->hdr),
  1627.             "and should be relinked");
  1628.     }
  1629.     return ZeroHeapEnd(execInfoPtr);
  1630.     }
  1631.     return(TRUE);
  1632. }
  1633.  
  1634.  
  1635. /*
  1636.  *----------------------------------------------------------------------
  1637.  *
  1638.  * ZeroHeapEnd --
  1639.  *
  1640.  *    Zero out the end of the heap (from the given address to the 
  1641.  *    next page boundary).  This routine exists for compatibility 
  1642.  *    with oddly-linked binaries.
  1643.  *
  1644.  * Results:
  1645.  *    TRUE if we were successful, FALSE if not (e.g., couldn't bring 
  1646.  *    in the last heap page).
  1647.  *
  1648.  * Side effects:
  1649.  *    None.
  1650.  *
  1651.  *----------------------------------------------------------------------
  1652.  */
  1653.     
  1654. static Boolean
  1655. ZeroHeapEnd(execInfoPtr)
  1656.     Vm_ExecInfo    *execInfoPtr;    /* info about the exec file */
  1657. {
  1658.     ReturnStatus    status;
  1659.     Address    heapEnd;    /* kernel address of end of heap */
  1660.     int        bytesToZero;    /* number of bytes to zero out */
  1661.     int        bytesAvail;    /* number of bytes accessible */
  1662.     int        userHeapEnd;
  1663.     
  1664.  
  1665.     status = Vm_PageIn((Address) ((execInfoPtr->bssFirstPage-1)*vm_PageSize),
  1666.                FALSE);
  1667.     if (status != SUCCESS) {
  1668.     printf("SetupVM: heap prefetch failure\n");
  1669.     return FALSE;
  1670.     }
  1671.     bytesToZero = execInfoPtr->heapExcess;
  1672.     userHeapEnd = execInfoPtr->bssFirstPage*vm_PageSize-bytesToZero;
  1673.     if (debugProcStubs) {
  1674.     printf("ZeroHeapEnd: zeroing %x at %x\n", bytesToZero, userHeapEnd);
  1675.     }
  1676.     Vm_MakeAccessible(VM_READWRITE_ACCESS, bytesToZero, (Address)userHeapEnd,
  1677.               &bytesAvail, (Address *)&heapEnd);
  1678.     if (bytesAvail != bytesToZero) {
  1679.     printf("SetupVM: can't map heap\n");
  1680.     return FALSE;
  1681.     }
  1682.     bzero((char *)heapEnd, bytesToZero);
  1683.     Vm_MakeUnaccessible(heapEnd, bytesToZero);
  1684.  
  1685.     return TRUE;
  1686. }
  1687.  
  1688.  
  1689. /*
  1690.  *----------------------------------------------------------------------
  1691.  *
  1692.  * ProcExecGetEncapSize --
  1693.  *
  1694.  *    Return the size of the encapsulated exec state.
  1695.  *
  1696.  * Results:
  1697.  *    SUCCESS is returned directly; the size of the encapsulated state
  1698.  *    is returned in infoPtr->size.
  1699.  *
  1700.  * Side effects:
  1701.  *    None.
  1702.  *
  1703.  *----------------------------------------------------------------------
  1704.  */
  1705.  
  1706. /* ARGSUSED */
  1707. ReturnStatus
  1708. ProcExecGetEncapSize(procPtr, hostID, infoPtr)
  1709.     Proc_ControlBlock *procPtr;            /* process being migrated */
  1710.     int hostID;                    /* host to which it migrates */
  1711.     Proc_EncapInfo *infoPtr;            /* area w/ information about
  1712.                          * encapsulated state */
  1713. {
  1714.     ExecEncapState *encapPtr;
  1715.  
  1716.     encapPtr = (ExecEncapState *) procPtr->remoteExecBuffer;
  1717.     encapPtr->hdr.fileNameLength =
  1718.     Byte_AlignAddr(strlen(encapPtr->hdr.fileName) + 1);
  1719.     encapPtr->hdr.argLength =
  1720.     Byte_AlignAddr(strlen(encapPtr->hdr.argString) + 1);
  1721.     infoPtr->size = encapPtr->hdr.size + encapPtr->hdr.fileNameLength +
  1722.     encapPtr->hdr.argLength;
  1723.     return(SUCCESS);    
  1724. }
  1725.  
  1726.  
  1727. /*
  1728.  *----------------------------------------------------------------------
  1729.  *
  1730.  * ProcExecEncapState --
  1731.  *
  1732.  *    Encapsulate the information needed to perform a remote exec,
  1733.  *    and return it in the buffer provided.
  1734.  *
  1735.  * Results:
  1736.  *    SUCCESS.  The buffer is filled.
  1737.  *
  1738.  * Side effects:
  1739.  *    None.
  1740.  *----------------------------------------------------------------------
  1741.  */
  1742.  
  1743. /* ARGSUSED */
  1744. ReturnStatus
  1745. ProcExecEncapState(procPtr, hostID, infoPtr, bufPtr)
  1746.     register Proc_ControlBlock     *procPtr;  /* The process being migrated */
  1747.     int hostID;                   /* host to which it migrates */
  1748.     Proc_EncapInfo *infoPtr;           /* area w/ information about
  1749.                         * encapsulated state */
  1750.     Address bufPtr;               /* Pointer to allocated buffer */
  1751. {
  1752.     ExecEncapState *encapPtr;
  1753.  
  1754.     encapPtr = (ExecEncapState *) procPtr->remoteExecBuffer;
  1755.  
  1756.     bcopy((Address) encapPtr, bufPtr, encapPtr->hdr.size);
  1757.     bufPtr += encapPtr->hdr.size;
  1758.     (void) strncpy(bufPtr, encapPtr->hdr.fileName, encapPtr->hdr.fileNameLength);
  1759.     bufPtr += encapPtr->hdr.fileNameLength;
  1760.     (void) strncpy(bufPtr, encapPtr->hdr.argString, encapPtr->hdr.argLength);
  1761.     return(SUCCESS);
  1762. }
  1763.  
  1764.  
  1765. /*
  1766.  *----------------------------------------------------------------------
  1767.  *
  1768.  * ProcExecDeencapState --
  1769.  *
  1770.  *    Get remote exec information from a Proc_ControlBlock from another host.
  1771.  *    The information is contained in the parameter ``buffer''.
  1772.  *
  1773.  * Results:
  1774.  *    SUCCESS.
  1775.  *
  1776.  * Side effects:
  1777.  *    Memory is allocated for argString, which is kept around while the
  1778.  *    process is alive.
  1779.  *----------------------------------------------------------------------
  1780.  */
  1781.  
  1782. /* ARGSUSED */
  1783. ReturnStatus
  1784. ProcExecDeencapState(procPtr, infoPtr, bufPtr)
  1785.     register Proc_ControlBlock     *procPtr; /* The process being migrated */
  1786.     Proc_EncapInfo *infoPtr;          /* information about the buffer */
  1787.     Address bufPtr;              /* buffer containing data */
  1788. {
  1789.     ExecEncapState *encapPtr;
  1790.     char *argString;
  1791.  
  1792.     procPtr->remoteExecBuffer = malloc(infoPtr->size);
  1793.     bcopy(bufPtr, procPtr->remoteExecBuffer, infoPtr->size);
  1794.  
  1795.     encapPtr = (ExecEncapState *) procPtr->remoteExecBuffer;
  1796.     encapPtr->hdr.fileName = procPtr->remoteExecBuffer + encapPtr->hdr.size;
  1797.     argString = encapPtr->hdr.fileName + encapPtr->hdr.fileNameLength;
  1798.     encapPtr->hdr.argString = malloc(encapPtr->hdr.argLength);
  1799.     (void) strncpy(encapPtr->hdr.argString, argString, encapPtr->hdr.argLength);
  1800.     return(SUCCESS);
  1801. }
  1802.  
  1803.  
  1804. /*
  1805.  *----------------------------------------------------------------------
  1806.  *
  1807.  * ProcExecFinishMigration --
  1808.  *
  1809.  *    Free up resources after a remote exec.  This includes buffers
  1810.  *      used to store information about a remote exec
  1811.  *    between the time of the system call and the time the migration
  1812.  *    completes: namely, the buffer containing the user's stack,
  1813.  *    and the file name to exec (reached via that buffer).  Also,
  1814.  *    free the virtual memory segments used by the process. 
  1815.  *
  1816.  * Results:
  1817.  *    SUCCESS.
  1818.  *
  1819.  * Side effects:
  1820.  *    Memory is freed. The segments are freed.
  1821.  *----------------------------------------------------------------------
  1822.  */
  1823.  
  1824. /* ARGSUSED */
  1825. ReturnStatus
  1826. ProcExecFinishMigration(procPtr, hostID, infoPtr, bufPtr, failure)
  1827.     register Proc_ControlBlock     *procPtr; /* The process being migrated */
  1828.     int hostID;                  /* Host to which it migrated */
  1829.     Proc_EncapInfo *infoPtr;          /* Information about the buffer */
  1830.     Address bufPtr;              /* Buffer containing data */
  1831.     Boolean failure;              /* Whether a failure occurred */
  1832. {
  1833.     ExecEncapState *encapPtr;
  1834.     int i;
  1835.  
  1836.     encapPtr = (ExecEncapState *) procPtr->remoteExecBuffer;
  1837.     free(encapPtr->hdr.fileName);
  1838.     free(procPtr->remoteExecBuffer);
  1839.     Proc_Lock(procPtr);
  1840.     procPtr->remoteExecBuffer = (Address) NIL;
  1841.     procPtr->genFlags |= PROC_NO_VM;
  1842.     Proc_Unlock(procPtr);
  1843.     for (i = VM_CODE; i <= VM_STACK; i++) {
  1844.     Vm_SegmentDelete(procPtr->vmPtr->segPtrArray[i], procPtr);
  1845.     }
  1846.     return(SUCCESS);
  1847. }
  1848.  
  1849.  
  1850. /*
  1851.  *----------------------------------------------------------------------
  1852.  *
  1853.  * ProcDoRemoteExec --
  1854.  *
  1855.  *    Do an exec of a process that's come to this machine from another
  1856.  *    one.  This is the PC at which the process resumes after migration,
  1857.  *    at which point it has no VM set up.
  1858.  *
  1859.  * Results:
  1860.  *    None.  This routine doesn't return, since upon error the process
  1861.  *    exits.
  1862.  *
  1863.  * Side effects:
  1864.  *    An exec is performed.
  1865.  *
  1866.  *----------------------------------------------------------------------
  1867.  */
  1868.  
  1869. void
  1870. ProcDoRemoteExec(procPtr)
  1871.     register Proc_ControlBlock *procPtr; /* Process control block, locked
  1872.                       * on entry */
  1873. {
  1874.     char *fileName = (char *) NIL;
  1875.     ReturnStatus status;
  1876.     ExecEncapState *encapPtr;
  1877.  
  1878.     /*
  1879.      * Set up dummy segments so that DoExec can work properly.
  1880.      */
  1881.  
  1882.     procPtr->genFlags &= ~PROC_REMOTE_EXEC_PENDING;
  1883.     procPtr->vmPtr->segPtrArray[VM_CODE] = 
  1884.                 Vm_SegmentNew(VM_CODE, (Fs_Stream *) NIL, 0,
  1885.                               1, 0, procPtr);
  1886.     if (procPtr->vmPtr->segPtrArray[VM_CODE] == (Vm_Segment *) NIL) {
  1887.     status = PROC_NO_SEGMENTS;
  1888.     Proc_Unlock(procPtr);
  1889.     goto failure;
  1890.     }
  1891.  
  1892.     procPtr->vmPtr->segPtrArray[VM_HEAP] =
  1893.             Vm_SegmentNew(VM_HEAP, (Fs_Stream *) NIL, 0, 1, 1, procPtr);
  1894.     if (procPtr->vmPtr->segPtrArray[VM_HEAP] == (Vm_Segment *) NIL) {
  1895.     Vm_SegmentDelete(procPtr->vmPtr->segPtrArray[VM_CODE], procPtr);
  1896.     status = PROC_NO_SEGMENTS;
  1897.     Proc_Unlock(procPtr);
  1898.     goto failure;
  1899.     }
  1900.  
  1901.     procPtr->vmPtr->segPtrArray[VM_STACK] =
  1902.             Vm_SegmentNew(VM_STACK, (Fs_Stream *) NIL, 
  1903.                    0 , 1, mach_LastUserStackPage, procPtr);
  1904.     if (procPtr->vmPtr->segPtrArray[VM_STACK] == (Vm_Segment *) NIL) {
  1905.     Vm_SegmentDelete(procPtr->vmPtr->segPtrArray[VM_CODE], procPtr);
  1906.     Vm_SegmentDelete(procPtr->vmPtr->segPtrArray[VM_HEAP], procPtr);
  1907.     status = PROC_NO_SEGMENTS;
  1908.     Proc_Unlock(procPtr);
  1909.     goto failure;
  1910.     }
  1911.  
  1912.     VmMach_ReinitContext(procPtr);
  1913.  
  1914.     encapPtr = (ExecEncapState *) procPtr->remoteExecBuffer;
  1915.     fileName = encapPtr->hdr.fileName;
  1916.     Proc_Unlock(procPtr);
  1917.     status = DoExec(fileName, (UserArgs *) NIL, &encapPtr, FALSE);
  1918.     /*
  1919.      * If the exec failed, then exit.  
  1920.      */
  1921.     failure:
  1922.     if (proc_MigDebugLevel > 0) {
  1923.     printf("Remote exec of %s failed: %s\n", fileName,
  1924.            Stat_GetMsg(status));
  1925.     }
  1926.     Proc_ExitInt(PROC_TERM_DESTROYED, SIG_KILL, 0);
  1927.     /*
  1928.      * NOTREACHED
  1929.      */
  1930. }
  1931.  
  1932.  
  1933. /*
  1934.  * The following table contains the functions to check if an executable
  1935.  * is of a particular machine type.
  1936.  */
  1937. int    hostFmt = HOST_FMT;
  1938. char * (*machType[]) _ARGS_((int bufferSize, char *buffer, int *magic, 
  1939.     int *syms, char **other)) =  {
  1940.     machType68k,
  1941.     machTypeSparc,
  1942. /*  machTypeSpur,   -- No longer supported */
  1943.     machTypeMips,
  1944. /*  machTypeSymm,   -- No longer supported */
  1945. };
  1946. /*
  1947.  *----------------------------------------------------------------------
  1948.  *
  1949.  * ProcIsObj -
  1950.  *
  1951.  *    Check if the process is an a.out file.  If doErr is set, an
  1952.  *    error message will be printed if the file is an a.out file.
  1953.  *    This routine is to be called if the file cannot be execed, to
  1954.  *    see if it's the wrong a.out type.
  1955.  *    This code is based on the Sprite a.out checking routines for
  1956.  *    the file program.
  1957.  *
  1958.  * Results:
  1959.  *    SUCCESS if the file is an a.out file.
  1960.  *    FAILURE if the file is not an a.out file.
  1961.  *
  1962.  * Side effects:
  1963.  *    An error may printed in the syslog if doErr is set.
  1964.  *
  1965.  *----------------------------------------------------------------------
  1966.  */
  1967. ReturnStatus
  1968. ProcIsObj(streamPtr, doErr)
  1969.     Fs_Stream    *streamPtr;    /* Stream pointer for obj file. */
  1970.     int        doErr;        /* 1 if want error messages. */
  1971. {
  1972.     ReturnStatus    status;
  1973.     char        *buffer;
  1974.     int            hdrSize = BUFSIZ;
  1975.     int            i;
  1976.     int            magic;
  1977.     char        *name;
  1978.     int            syms;
  1979.     char        *other;
  1980.  
  1981.     buffer = (char *)malloc(hdrSize);
  1982.     status = Fs_Read(streamPtr, (Address)buffer, 0, &hdrSize);
  1983.     if (status != SUCCESS) {
  1984.     return FAILURE;
  1985.     }
  1986.     for (i=0; i < sizeof(machType)/sizeof(*machType); i++) {
  1987.     name = machType[i](hdrSize, (const char *) buffer, &magic, &syms,
  1988.         &other);
  1989.     if (name != NULL) {
  1990.         if (doErr) {
  1991.         printf("Proc_Exec: Can't run %s ", name);
  1992.         switch (magic) {
  1993.             case 0407:
  1994.             printf("OMAGIC");
  1995.             break;
  1996.             case 0410:
  1997.             printf("NMAGIC");
  1998.             break;
  1999.             case 0413:
  2000.             printf("ZMAGIC");
  2001.             break;
  2002.             case 0414:
  2003.             printf("SPRITE_ZMAGIC");
  2004.             break;
  2005.             case 0415:
  2006.             printf("UNIX_ZMAGIC");
  2007.             break;
  2008.             case 0443:
  2009.             printf("LIBMAGIC");
  2010.             break;
  2011.             default:
  2012.             printf("(0%03o)", magic);
  2013.             break;
  2014.         }
  2015.         if (*other != '\0') {
  2016.             printf(" %s", other);
  2017.         }
  2018.         printf(" executable file on %s.\n", mach_MachineType);
  2019.         }
  2020.         return SUCCESS;
  2021.     }
  2022.     }
  2023.     return FAILURE;
  2024. }
  2025.